import { Destroy, Provide, Scope, ScopeEnum } from "@midwayjs/core";

import { PrismaClient as INOVANCE_FC_F_ROOT } from "@prisma/INOVANCE_FC_F_ROOT";
import { PrismaClient as INOVANCE_FR_F_ROOT } from "@prisma/INOVANCE_FR_F_ROOT";
import { PrismaClient as INOVANCE_FR_B_ROOT } from "@prisma/INOVANCE_FR_B_ROOT";
import { PrismaClient as PERFORMANCE_F_ROOT } from "@prisma/PERFORMANCE_F_ROOT";
import { ClientManager, PrismaKey, PrismaQueen } from "@/typings/indexD";
import { LogUtils } from "../log";

/**
 * ## Prisma代理工具
 * 
 * @example
 * ```
 * import { PrismaUtils } from "@/util/index";
 * const dbs = PrismaUtils.INOVANCE_FS_F_ROOT_Client;
 * ```
 */
@Provide()
@Scope(ScopeEnum.Singleton)
export class PrismaUtils extends LogUtils {
    /** 连接管理器 */
    private readonly clients = new Map<PrismaKey, ClientManager<any>>();

    /** 连接计数器 */
    private activeConnections = 0;

    /** 配置参数 */
    private readonly config = {
        idleTimeout: 5 * 60 * 1000, // 5分钟闲置断开
        checkInterval: 60 * 1000,   // 每分钟检查一次
        maxIdleChecks: 5,           // 最大空闲检查次数
    };

    /** 按需初始化的定时器 */
    private idleTimer: NodeJS.Timeout | null = null;
    private idleCheckCounter = 0;

    /** 按需获取或创建客户端 */
    private getOrCreateClient<K extends PrismaKey>(name: K): PrismaQueen<K> {
        if (!this.clients.has(name)) {
            const instance = this.createClientInstance(name);

            this.clients.set(name, {
                instance,
                lastUsed: Date.now(),
                queryCount: 0
            });

            this.activeConnections++;
            this.logger.info(`[$${name}] 连接已创建 (活动连接: $${this.activeConnections})`);

            // 按需启动定时器
            this.startIdleTimer();
        }

        const client = this.clients.get(name)!;
        client.lastUsed = Date.now();
        client.queryCount++;
        return client.instance;
    }

    /** 创建客户端实例 */
    private createClientInstance(name: PrismaKey) {
        switch (name) {
            case "INOVANCE_FC_F_ROOT": return new INOVANCE_FC_F_ROOT();
            case "INOVANCE_FR_F_ROOT": return new INOVANCE_FR_F_ROOT();
            case "INOVANCE_FR_B_ROOT": return new INOVANCE_FR_B_ROOT();
            case "PERFORMANCE_F_ROOT": return new PERFORMANCE_F_ROOT();
            default: throw new Error(`未定义的数据库客户端: ${name}`);
        }
    }

    /** 启动闲置检查定时器 */
    private startIdleTimer() {
        if (!this.idleTimer) {
            this.idleTimer = setInterval(async () => {
                const released = await this.checkAllIdle();

                // 无连接时停止定时器
                if (this.activeConnections === 0) {
                    this.stopIdleTimer();
                }

                // 防止长期空转
                if (released === 0) {
                    this.idleCheckCounter++;
                    if (this.idleCheckCounter > this.config.maxIdleChecks) {
                        this.logger.debug('空闲检查器进入休眠');
                        this.stopIdleTimer();
                    }
                } else {
                    this.idleCheckCounter = 0;
                }
            }, this.config.checkInterval);
            this.logger.info('闲置连接检查器已启动');
        }
    }

    /** 停止闲置检查定时器 */
    private stopIdleTimer() {
        if (this.idleTimer) {
            clearInterval(this.idleTimer);
            this.idleTimer = null;
            this.idleCheckCounter = 0;
            this.logger.info('闲置连接检查器已停止');
        }
    }

    /** 检查所有连接的闲置状态 */
    private async checkAllIdle(): Promise<number> {
        if (this.activeConnections === 0) return 0;

        const now = Date.now();
        let releasedCount = 0;

        for (const [name, client] of this.clients.entries()) {
            if (now - client.lastUsed > this.config.idleTimeout) {
                try {
                    await client.instance.$disconnect();
                    this.clients.delete(name);
                    this.activeConnections--;
                    releasedCount++;

                    this.logger.info(
                        `[$${name}] 连接释放 | 查询次数: $${client.queryCount} | ` +
                        `活动连接: ${this.activeConnections}`
                    );
                } catch (error) {
                    this.logger.error(`[$${name}] 连接释放失败: $${(error as Error).message}`);
                }
            }
        }

        return releasedCount;
    }

    /** 
     * 获取指挥平台数据库
     * fbi_configs
     */
    get INOVANCE_FC_F_ROOT_Client(): PrismaQueen<"INOVANCE_FC_F_ROOT"> {
        return this.getOrCreateClient("INOVANCE_FC_F_ROOT");
    }

    /** 
     * 获取正式写库-root数据库
     * inovance_fr
     */
    get INOVANCE_FR_F_ROOT_Client(): PrismaQueen<"INOVANCE_FR_F_ROOT"> {
        return this.getOrCreateClient("INOVANCE_FR_F_ROOT");
    }

    /** 
     * 获取正式读库-root数据库
     * inovance_fr
     */
    get INOVANCE_FR_B_ROOT_Client(): PrismaQueen<"INOVANCE_FR_B_ROOT"> {
        return this.getOrCreateClient("INOVANCE_FR_B_ROOT");
    }

    /** 
     * 绩效系统数据库
     * inovance_performance_pro
     */
    get PERFORMANCE_F_ROOT_Client(): PrismaQueen<"PERFORMANCE_F_ROOT"> {
        return this.getOrCreateClient("PERFORMANCE_F_ROOT");
    }

    /** 应用退出时清理资源 */
    @Destroy()
    async onDestroy() {
        // 停止定时器
        this.stopIdleTimer();

        // 并行释放所有连接
        const releasePromises = Array.from(this.clients.entries()).map(
            async ([name, client]) => {
                try {
                    await client.instance.$disconnect();
                    this.logger.info(`[${name}] 连接已关闭`);
                } catch (error) {
                    this.logger.error(`[$${name}] 关闭失败: $${(error as Error).message}`);
                }
            }
        );

        await Promise.allSettled(releasePromises);

        // 强制清理
        this.clients.clear();
        this.activeConnections = 0;

        this.logger.info(`资源清理完成 | 释放连接: ${releasePromises.length}`);
    }
}